function FilterControllerSearch(element){
    this.element = element;
    this.element.on("input",function(){this.onChange()}.bind(this));
}
FilterControllerSearch.prototype = {
    constructor: FilterControllerSearch,
    getValue: function(){
        value = this.element.val();
        return value==""?null:value;
    },
    setValue: function(value){
        this.element.val(value===null?"":value);
    },
    onChange:function(){}
}

function FilterControllerWfCheckbox(element){
    this.element = element;
    this.element.parent().find("input[type='checkbox']").change(function(){this.onChange()}.bind(this));
}
FilterControllerWfCheckbox.prototype = {
    constructor: FilterControllerWfCheckbox,
    getValue: function(){
        d = this.element.parent().find("input[type='checkbox']").first();
        return d.prop('checked');
    },
    setValue: function(value){
      d = this.element.parent().find("input[type='checkbox']").first();
      if(value && !d.prop('checked')){
        d.click();
      }else if(!value && d.prop('checked')){
        d.click();
      }
      }
    ,
    onChange: function(){}
}

function FilterControllerCheckbox(element){
    this.element = element;
    this.element.change(function(){this.onChange()}.bind(this));
}
FilterControllerCheckbox.prototype = {
    constructor: FilterControllerCheckbox,
    getValue: function(){
           return this.element.prop('checked');
    },
    setValue: function(selected){
        this.element.prop('checked',selected);
    },
    onChange: function(){}
}

function FilterControllerChip(element){
    this.element = element;

    this.element.click(function(){
        this.element.toggleClass("ncf-selected");
        this.onChange();
    }.bind(this));
}
FilterControllerChip.prototype = {
    constructor: FilterControllerChip,
    getValue: function(){
        return this.element.hasClass("ncf-selected");
    },
    setValue: function(val){
      x=val?this.element.addClass("ncf-selected"):this.element.removeClass("ncf-selected");
    },
    onChange: function(){}
}

function FilterControllerCategory(elements){

    this.elements = elements;
    this.controller = [];
    this.elements.each(function(i,o){
        var clt;
        if($(o).hasClass("ncf-filter-categorie-chip")){
            clt=new FilterControllerChip($(o));
            val = $(o).data("value");
        }else if($(o).hasClass("ncf-filter-categorie-checkbox")){
            if($(o).hasClass("w-checkbox-input--inputType-custom")){
                clt=new FilterControllerWfCheckbox($(o));
                val = $(o).parent().find("input[type='checkbox']").first().data("value");
            }else{
                clt=new FilterControllerCheckbox($(o));
                val = $(o).data("value");
            }
        }else{
            console.error("Error: ControllerCategory called with wrong elements!!");
        }
        const c = clt;
        const v = val;
        c.onChange = function(){this.change(c,v)}.bind(this);

        if(val in this.controller){
            this.controller[val].push(c);
        }else{
            this.controller[val] = [c];
        }
    }.bind(this));
}
FilterControllerCategory.prototype = {
    constructor: FilterControllerCategory,
    getValue: function(){
        values = [];
        for(k in this.controller){
            if(this.controller[k][0].getValue()){
                values.push(k);
            }
        }
        return values;
    },
    setValue: function(val){
      for(k in this.controller){
        for(c of this.controller[k]){
            c.setValue(val === k);
        }
      }
    },
    change: function(controller,val){
        for(c of this.controller[val]){
            c.setValue(controller.getValue());
        }
        this.onChange();
    },
    onChange: function(){}
}

function FilterObject(type, key,controller){
    this.key = key;
    this.type = type;
    this.controller = controller;
}
FilterObject.prototype = {
    constructor: FilterObject,
    setValue: function(value){
        this.value = value;
    },
    getFilter:function(){
        var value = this.controller.getValue();
        if(Array.isArray(value)){
            var filter = [];
            for(val of value){
                filter.push({type: this.type ,key: this.key, value: val});
            }
            if(filter.length == 0){
                return null;
            }
            return ({type:"group", items: filter});
        }else{
            if(value == null){
                return null;
            }
            return ({type: this.type,key: this.key,value: value});
        }
    }

}
function FilterList(root){
    this.root = root;
    this.container = this.root.find(".ncf-filter-item-container");
    this.itemList = [];
    this.controller = [];
    this.filterObjects = [];
    this.page = 0;
    this.perPage = this.root.data("items-per-page")||20
    console.log(this.perPage);
    this.currentFilter = [];
    this.orderby = null;
    this.root.find(".ncf-next-page").click(this.nextPage.bind(this))
    this.root.find(".ncf-prev-page").click(this.prevPage.bind(this))
    this.root.find(".ncf-filter-reset").click(this.reset.bind(this))
    this.emptyState = this.root.find(".ncf-empty-state").clone(true, true);
    this.root.find(".ncf-empty-state").remove();
    this.initController();
    this.container.find(".ncf-filter-item").each(function(i,o){
        this.itemList.push(new FilterListItem($(o)));
    }.bind(this));
    this.maxPage = Math.max(0,Math.floor((this.itemList.length-1)/this.perPage));
    this.update(undefined, true);
}

FilterList.prototype = {
    constructor: FilterList,
    nextPage: function(){
        if(this.page<this.maxPage)
        this.update(this.page+1);
    },

    initController: function(){
        search = this.root.find(".ncf-filter-control-search");
        order = this.root.find(".ncf-filter-order");
        order.change(this.update.bind(this));
        categorie = this.root.find(".ncf-filter-categorie-checkbox,.ncf-filter-categorie-chip");
        search.each(function(i,o){
            const ctl = new FilterControllerSearch($(o));
            this.controller.push(ctl);
            this.filterObjects[$(o).data("filter")] = new FilterObject("search",$(o).data("filter"),ctl);
        }.bind(this));
        keys = []
        categorie.each(function(i,o){
            if($(o).hasClass("w-checkbox-input--inputType-custom")){
                key = $(o).parent().find("input[type='checkbox']").first().data("filter");
            }else{
                key = $(o).data("filter")
            }
            if(!keys.includes(key)){
                keys.push(key);
            }

        }.bind(this));
        for(k of keys){

            ctl = new FilterControllerCategory(this.root.find(".w-checkbox>*[data-filter='"+k+"']").parent().children(".ncf-filter-categorie-checkbox").add(this.root.find(".ncf-filter-categorie-chip[data-filter='"+k+"']")) );
            this.controller.push(ctl);
            this.filterObjects[k] = new FilterObject("equal",k,ctl);
        }
        for(ct of this.controller){
            ct.onChange = function(){
                this.update();
            }.bind(this);
        }
    },

    prevPage: function(){
        if(this.page>0)
        this.update(this.page-1);
    },
    updatePageIndicator: function(){
        next = this.root.find(".ncf-next-page");
        prev = this.root.find(".ncf-prev-page");
        if(this.maxPage == 0){
            this.root.find(".ncf-filter-page-indicator").hide();
        }else{
            this.root.find(".ncf-filter-page-indicator").show();
        }
        if(this.page == this.maxPage){next.hide();} else{next.show();}
        if(this.page == 0){ prev.hide();} else{ prev.show();}
        this.root.find(".ncf-current-page").html((this.page-0)+1);
        this.root.find(".ncf-max-page").html(this.maxPage+1);
    },
    onUpdate:function(){},
    reset: function(){
      for(c of this.controller){
        c.setValue(null);
      }
      this.update();
    },

    update: function(page = this.page, changed = false){
        filter = [];

        for(flt in this.filterObjects){
            tempFilter = this.filterObjects[flt].getFilter();
            if(tempFilter == null){
                continue;
            }
            filter.push(tempFilter);
        }
        console.log(filter);
        if(filter.length == 0){
            this.root.find(".ncf-filter-target").addClass("ncf-filter-no");
            this.root.find(".ncf-filter-target").removeClass("ncf-filter-yes");
        }else{
            this.root.find(".ncf-filter-target").addClass("ncf-filter-yes");
            this.root.find(".ncf-filter-target").removeClass("ncf-filter-no");
        }
        orderby = this.root.find(".ncf-filter-order").val();
        changed = this.orderby !== orderby;
        this.orderby = orderby;
        if(JSON.stringify(filter) !== JSON.stringify(this.currentFilter) || changed){
            this.page = 0;
            this.currentFilter = filter;
            displayList = this.itemList.filter(function(item){return item.filter(this.currentFilter)}.bind(this))
        }else if(page!=this.page){
            this.page = page;
            displayList = this.itemList.filter(function(item){return item.filter(this.currentFilter)}.bind(this))
        }else{
            this.updatePageIndicator();
            return;
        }



        displayList.sort(function(a,b){
            console.log(a.data[this.orderby],this.orderby);
            return (a.data[this.orderby]<b.data[this.orderby])?-1:1

        });
        console.log(displayList);
        this.maxPage = Math.max(Math.floor((displayList.length-1)/this.perPage),0);
        this.container.html("");
        if(displayList.length == 0){
            this.container.append(this.emptyState.clone(true,true));
        }
        for (item of displayList.slice(this.page*this.perPage,(this.page+1)*this.perPage)){
            item.append(this.container);
        }
        this.updatePageIndicator();
        this.onUpdate();
    }
}


function FilterListItem(wrapper){
    this.root = wrapper;
    this.data = this.root.find(".identifyer").data();
    this.template = $(wrapper).clone();
}

FilterListItem.prototype = {
    constructor: FilterListItem,
    filter: function(filterlist,and=true){
        equalset = false;
        for(filter of filterlist){
            if(filter.type == "group"){
                resp = this.filter(filter.items,false);
                if(and && !resp){
                    return false;
                }
                if(!and && resp){
                    return true;
                }
            }
            if(filter.type == "search"){
                if(!this.data[filter.key].toLowerCase().includes(filter.value.toLowerCase())) return false;
            }
            if(filter.type != "equal") continue;
            equalset = true;
            if(and && ( !filter.key in this.data ||this.data[filter.key] != filter.value)){
                return false;
            }
            if(!and && this.data[filter.key] == filter.value){
                return true;
            }
        }
        return !equalset|| and;
    },
    getOrderIndex: function(crit){
        return crit in this.data?this.data[crit]:Number.MAX_SAFE_INTEGER
    },
    sortHelper: function(other, crit){
        return this.getOrderIndex(crit)-other.getOrderIndex(crit)
    },
    append: function(onto){
        onto.append(this.template);
    },
}

$(document).ready(()=>{
  	$(".ncf-filterlist").not('.ncf-map').each((i,o)=>{
  	    new FilterList($(o));
  	});
});



